/*
    Superjuego Engine
    Copyright (C) 2011 Jorge Luís Cabral y Gabriel Ernesto Cabral

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public
    License as published by the Free Software Foundation; either
    version 2 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Library General Public License for more details.

    You should have received a copy of the GNU Library General Public
    License along with this library; if not, write to the Free
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

    Contact: baigosoft@hotmail.com
*/

//#include "render.h"
#include "super.h"

float screen_width;
float screen_height;

pvr_init_params_t params = {
	/* Enable opaque and translucent polygons with size 16 */
	{ PVR_BINSIZE_16, PVR_BINSIZE_0, PVR_BINSIZE_16, PVR_BINSIZE_0, PVR_BINSIZE_0 },
	
	/* Vertex buffer size 512K */
	512*1024
};

static inline void plx_vert_ifpm3(int flags, float x, float y, float z, uint32 color, float u, float v) {	
	plx_mat_tfip_3d(x, y, z);
	plx_vert_ifp(flags, x, y, z, color, u, v);
	//printf("%f %f %f\n",x,y,z);
}


//SDL_Surface *screen;

int SE_screen_init(int width,int height,int bpp)
{
	//hack, inicializar bien, "como se debe"
	//pvr_init_defaults();
	
	vid_set_mode(DM_640x480_VGA, PM_RGB565);
	if (pvr_init(&params) < 0)
		return -1;

	screen_width=width;
	screen_height=height;

	//
	//pvr_init_defaults();


	// Setup the frame COMENTADO TEMPORALMENTE O SINO NO ARRANCA EL LXDREAM
	//pvr_wait_ready();

	pvr_scene_begin();
	/*pvr_list_begin(PVR_LIST_OP_POLY);
	pvr_list_finish();
	pvr_list_begin(PVR_LIST_PT_POLY);
	pvr_list_finish();*/
	pvr_list_begin(PVR_LIST_TR_POLY);
	

	/* Init matrices */
	plx_mat3d_init();                    /* Clear internal to an identity matrix */
	plx_mat3d_mode(PLX_MAT_PROJECTION);  /** Projection (frustum, screenview) matrix */
	plx_mat3d_identity();                /** Load an identity matrix */
	plx_mat3d_perspective(45.0f, 640.0f / 480.0f, 100.0f, 0.1f);  // (float angle, float aspect, float znear, float zfar);
	plx_mat3d_mode(PLX_MAT_MODELVIEW);   /** Modelview (rotate, scale) matrix */
	
//	oplist=SE_list_new();
//	ptlist=SE_list_new();
//	trlist=SE_list_new();

	
	return 1;
	
}

void enable2d()							
{
			
}


void disable2d()							
{
				
}


void SE_screen_clear(float r,float g,float b,float a)
{
	pvr_set_bg_color(r,g,b);
}



SE_image *SE_image_load(char *path)
{
		
	SE_image *img;
	int flags=0;
	int fnlen;

	printf("Cargando textura: %s\n",path);

	//plx_texture_t * txr;
	img = (SE_image*)malloc(sizeof(SE_image));
	
	fnlen = strlen(path);
	if (!strcasecmp(path + fnlen - 3, "kmg")) {
	
	flags=PVR_TXRLOAD_FMT_VQ|PVR_TXRLOAD_FMT_TWIDDLED;

	}
	img->texture = plx_txr_load(path, 1, flags);
	if (!img->texture)
		printf("no se pudo cargar la textura\n");

	
//	img->texture = txr;//loadTexture(temp);

	img->w = img->texture->w;
	img->h = img->texture->h;
	
	img->x = 0;
	img->y = 0;
//	img->z = 0;

	
/*	img->rotx = 0;
/	img->roty = 0;
	img->rotz = 0;

	img->r = 1.0;
	img->g = 1.0;
	img->b = 1.0;

	img->alpha = 1.0;*/
	
			//printf("x: %d\ny: %d\nancho: %d\nalto: %d\n",img->x,img->y,img->w,img->h);

	//SDL_FreeSurface(temp);
	return img;

}



void SE_image_draw(SE_image *img,float posx,float posy,float posz)
{

	SE_image_full_draw(img,posx,posy,posz,1,1,0,0,0,1,1,1,1);

}


void SE_image_full_draw(SE_image *img,float posx,float posy,float posz,float zoomx,float zoomy,float rotx,float roty,float rotz,float r,float g,float b,float alpha)
{
	
	SE_image_segment_draw(img,0,0,img->w,img->h,posx,posy,posz,zoomx,zoomy,rotx,roty,rotz,r,g,b,alpha);

}


void SE_image_segment_draw(SE_image *img,float xtex,float ytex,float wtex,float htex,float posx,float posy,float posz,float zoomx,float zoomy,float rotx,float roty,float rotz,float r,float g,float b,float alpha)
{

int w = img->w;
int h = img->h;

int x = img->x;
int y = img->y;
//int z = img->z;
//float zx = img->w*zoomx;
//float zy = img->w*zoomy;

float width = wtex * zoomx;
float height = htex * zoomy;

float zx = wtex;
float zy = htex;

float x1 = xtex/w;
float y1 = ytex/h;
float x2 = (xtex + wtex)/w;
float y2 = (ytex + htex)/h;


//	printf("posz:%f\n",posz);

/*	if(alpha==1){
		SE_list_add(oplist,posx,posy,posz,rotx,roty,rotz);
	}else{
		SE_list_add(trlist,posx,posy,posz,rotx,roty,rotz);
	}*/

		plx_mat3d_identity();
//	plx_mat3d_apply(PLX_MAT_SCREENVIEW);
//	plx_mat3d_apply(PLX_MAT_PROJECTION);
//	plx_mat3d_apply(PLX_MAT_MODELVIEW);
		plx_mat3d_translate((wtex/2)+posx,(htex/2)+posy,0);       // ubicar el objeto en x,y,z
//		plx_mat3d_push();
	    
		/* Clear internal to an identity matrix */
//		plx_mat_identity();
	    
		/* "Applying" all matrixs: multiply a matrix onto the "internal" one */
//		plx_mat3d_identity();
		plx_mat3d_apply_all();

//		plx_mat3d_translate((wtex/2)+posx,(htex/2)+posy,-posz);       // ubicar el objeto en x,y,z
		// Setup a texture context
		plx_mat3d_rotate(rotx, 1.0f, 0.0f, 0.0f); // Rotate the BOX angle 'xrot' on the X axis   
		plx_mat3d_rotate(roty, 0.0f, 1.0f, 0.0f); // Rotate the BOX angle 'yrot' on the Y axis
		plx_mat3d_rotate(rotz, 0.0f, 0.0f, 1.0f); // Rotate the BOX angle 'yrot' on the Y axis


		plx_cxt_init();
		plx_cxt_texture(img->texture);
		plx_cxt_culling(PLX_CULL_NONE);
		plx_cxt_send(PVR_LIST_TR_POLY);

		plx_mat3d_translate(0, 0, 0); //ubicar EL CENTRO del objeto


		plx_vert_ifpm3(PLX_VERT, -zx/2, zy/2, posz, 0xffffffff, x1, y2);
		plx_vert_ifpm3(PLX_VERT, -zx/2, -zy/2, posz, 0xffffffff, x1, y1);
		plx_vert_ifpm3(PLX_VERT, zx/2, zy/2, posz, 0xffffffff, x2, y2);
		plx_vert_ifpm3(PLX_VERT_EOS, zx/2, -zy/2, posz, 0xffffffff, x2, y1);

//		plx_mat3d_pop();

		SE_utils_logvertices(4);

}

void SE_image_triangle_set(float posx,float posy,float posz,float rotx, float roty, float rotz,float zoom)
{
		plx_mat_identity();	    
//	    	plx_mat3d_translate(640/2,480/2,0);       // ubicar el objeto en x,y,z
	    	plx_mat3d_translate(posx,posy,-posz);       // ubicar el objeto en x,y,z
		/* "Applying" all matrixs: multiply a matrix onto the "internal" one */
//		plx_mat_identity();	    

		plx_mat3d_scale(zoom,zoom,zoom);
		plx_mat3d_rotate(rotx, 1.0f, 0.0f, 0.0f); // Rotate the BOX angle 'xrot' on the X axis   
		plx_mat3d_rotate(roty, 0.0f, 1.0f, 0.0f); // Rotate the BOX angle 'yrot' on the Y axis
		plx_mat3d_rotate(rotz, 0.0f, 0.0f, 1.0f); // Rotate the BOX angle 'yrot' on the Y axis


}

void SE_image_triangle_finish()
{
		plx_mat_identity();
		plx_mat3d_apply_all();


}

void SE_image_triangle_draw(SE_image *img,SE_vector *vertex,float *u,float *v)
{


		plx_cxt_init();
		plx_cxt_texture(img->texture);
		plx_cxt_culling(PLX_CULL_CCW);
		plx_cxt_send(PVR_LIST_TR_POLY);


//		SE_list_add(oplist,vertex[0].x,vertex[0].y,vertex[0].z,0,0,0);
//		SE_list_add(oplist,vertex[1].x,vertex[1].y,vertex[1].z,0,0,0);
//		SE_list_add(oplist,vertex[2].x,vertex[2].y,vertex[2].z,0,0,0);


//		plx_mat3d_translate(0, 0, 0); //ubicar EL CENTRO del objeto
//		plx_mat3d_apply_all();

		/* Clear internal to an identity matrix */
//		plx_mat3d_translate(0, 0, 0); //ubicar EL CENTRO del objeto


		plx_vert_ifpm3(PLX_VERT, vertex[0].x, vertex[0].y, vertex[0].z, 0xffffffff, u[0], v[0]);
		plx_vert_ifpm3(PLX_VERT, vertex[1].x, vertex[1].y, vertex[1].z, 0xffffffff, u[1], v[1]);
		plx_vert_ifpm3(PLX_VERT_EOS, vertex[2].x, vertex[2].y, vertex[2].z, 0xffffffff, u[2], v[2]);

		SE_utils_logvertices(3);

}



void SE_image_clean(SE_image *img)
{

	free(img);
	if(img != 0)
	{
		printf("error, no se pudo borrar puntero de imagen");
	}
	

}

void SE_screen_flip()
{

	SE_nodo *nodo;
	// Setup the frame
//	pvr_wait_ready();

	pvr_list_finish();
	pvr_scene_finish();//flipea la escena

	//hack para que funcione el lxdream, con wait_ready debería ser suficiente en el hardware real
	while(pvr_check_ready()!=0){

	}
	pvr_wait_ready();
	pvr_scene_begin();
	/*pvr_list_begin(PVR_LIST_OP_POLY);
	pvr_list_finish();
	pvr_list_begin(PVR_LIST_PT_POLY);
	pvr_list_finish();*/
	pvr_list_begin(PVR_LIST_TR_POLY);


//	printf("lista op:%d\n",SE_list_size(oplist));
//	printf("lista pt:%d\n",SE_list_size(ptlist));
//	printf("lista tr:%d\n",SE_list_size(trlist));
/*	nodo=oplist->first;
	while(nodo->next){
		printf("draw vert:%f %f %f\n",nodo->x,nodo->y,nodo->z);
		nodo=nodo->next;		
	}*/
	
//	SE_list_free(oplist);
//	SE_list_free(trlist);
//	SE_list_free(ptlist);

}

void SE_image_position(SE_image *img,float posx,float posy)
{

	img->x = posx;
	img->y = posy;
//	img->z = posz;

}

void SE_image_size(SE_image *img,int width,int height)
{
	
	img->w = width;
	img->h = height;

}

void SE_image_zoomx(SE_image *img,float zoomx)
{
	
	if(zoomx < 0.0)printf("el zoom no puede ser menor a 0"); 
//	img->zoomx = zoomx;

}

void SE_image_zoomy(SE_image *img,float zoomy)
{
	
	if(zoomy < 0.0)printf("el zoom no puede ser menor a 0");
//	img->zoomy = zoomy;

}

void SE_image_zoom(SE_image *img,float zoom)
{
	
	SE_image_zoomx(img,zoom);
	SE_image_zoomy(img,zoom);
	
}


/*void SE_image_rotationx(SE_image *img,float rotationx)
{

	img->rotx = rotationx;

}
void SE_image_rotationy(SE_image *img,GLfloat rotationy)
{

//	img->roty = rotationy;

}
void SE_image_rotationz(SE_image *img,GLfloat rotationz)
{

//	img->rotz = rotationz;	

}*/

/*void SE_image_rotation(SE_image *img,GLfloat rotationx,GLfloat rotationy,GLfloat rotationz)
{

	SE_image_rotationx(img,rotationx);
	SE_image_rotationy(img,rotationy);
	SE_image_rotationz(img,rotationz);

}


void SE_image_alpha(SE_image *img,float alpha_magnitude)
{
	if(alpha_magnitude < 0.0)alpha_magnitude = 0.0;
	if(alpha_magnitude > 1.0)alpha_magnitude = 1.0;
	img->alpha = alpha_magnitude;

}*/

void SE_image_tint(SE_image *img,float red,float green,float blue)
{
//	img->r = red;
//	img->g = green;	
//	img->b = blue;

}

void SE_image_light(SE_image *img,float light_intensity)
{
	if((light_intensity < 0.0)||(light_intensity > 1.0))printf("la intensidad de la luz debe estar entre 0 y 1");
	SE_image_tint(img,light_intensity,light_intensity,light_intensity);
	

}

void SE_drawrectangle(float x,float y,float z,float width,float height,int fill,float red,float green,float blue,float alpha)
{


}

